#pragma once
#include "public.hpp"
using namespace std;

using functask_t = function<void(int, string, const Analyze)>;

class UdpServer
{
private:
    uint16_t _port; // 服务端端口号
    int _sockfd;

    // unordered_map<string, uint16_t> usersinfo;
    unordered_multimap<string, uint16_t> usersinfo;

    queue<string> qs;
    functask_t _func;

public:
    UdpServer() {}

    UdpServer(uint16_t port, functask_t func) : _port(port), _func(func)
    {
    }
    ~UdpServer()
    {
    }

    void Init()
    {
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0); // UDP
        if (_sockfd < 0)
        {
            Log(Fatal, "socket create error");
            exit(SOCK_CREATE_ERROR);
        }
        // socket创建成功

        // 接下来需要将socket与网络信息进行绑定
        struct sockaddr_in server;
        bzero(&server, 0);

        server.sin_addr.s_addr = 0; // 表示绑定本机任意ip地址
        server.sin_family = AF_INET;
        server.sin_port = htons(_port);

        socklen_t len = sizeof(server);
        int bindval = bind(_sockfd, (struct sockaddr *)&server, len);
        if (bindval < 0)
        {
            Log(Fatal, "socket bind error");
            exit(SOCK_BIND_ERROR);
        }
        // 绑定成功
        Log(Info, "socket init success");
    }
    
    void GetInfo()
    {
     
        char buffer[1024]; bzero(buffer, sizeof(buffer));
        struct sockaddr_in client;  bzero(&client, sizeof(client));
        
        socklen_t len = sizeof(client);

        while (true)
        {           
            ssize_t realnum = recvfrom(_sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &len);
            if (realnum < 0)
            {
                Log(Error, "get clientinfo error");
                continue;
            }
            
            Analyze ret(client);
            buffer[realnum] = '\0';
            cout << "[server message from: " << ret.getip() << "]: " << buffer << endl;

            qs.push(buffer); //缺少比较逻辑
            _func(_sockfd, buffer, ret);
            // usersinfo[ret.getip()] = ret.getport();       
        }
    }

    // void SendInfo()
    // {
    //     struct sockaddr_in client;
    //     bzero(&client, 0);

    //     while (true)
    //     {
    //         if(qs.empty()) continue;
    //         string str = qs.front();
    //         qs.pop();
    
    //         client.sin_family = AF_INET;
           
    //         socklen_t len = sizeof(client);
    //         for(auto &e: usersinfo)
    //         {
    //             client.sin_port = htons(e.second);
    //             client.sin_addr.s_addr = inet_addr(e.first.c_str());
    //             ssize_t val = sendto(_sockfd, str.c_str(), str.size(), 0, (struct sockaddr *)&client, len);
    //         }
    //     }
    // }

    // 在这里要实现多线程，使用线程池，在全局预先创建好线程池
    // 服务端接受和发送消息方法分开写，且为静态
    void Start()
    {
        ThreadPool<function<void()>> *Pool = ThreadPool<function<void()>>::GetPool();

        Pool->ThreadInit();
        Pool->Start();

        function<void()> func1 = bind(&UdpServer::GetInfo, this);
        Pool->Push(func1);

        // function<void()> func2 = bind(&UdpServer::SendInfo, this);
        // Pool->Push(func2);

        Pool->Wait();
    }
};